package kr.pe.osdev.dao.jdbc.mysql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import kr.pe.osdev.common.util.StringConvertor;
import kr.pe.osdev.dao.UserDao;
import kr.pe.osdev.dao.jdbc.BaseJdbcDao;
import kr.pe.osdev.domain.User;
import kr.pe.osdev.security.UserGrantedAuthority;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.userdetails.memory.UserAttribute;
import org.springframework.stereotype.Repository;

//@Component("userDaoImpl")
@Repository
public class UserDaoImpl extends BaseJdbcDao implements UserDao {
	protected final Log logger = LogFactory.getLog(getClass());

	@Override
	public User add(User user) throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.add");

        Object[] obj = new Object[] { user.getSid(),
                                    user.getPid(),
                                    user.getUserId(),
                                    user.getPasswd(),
                                    user.getEmail(),
                                    user.getUserName(),
                                    user.getNickName(),
                                    user.getImgFile(),
                                    user.getIconFile(),
                                    StringConvertor.convertorBooleanToString(user.isEnabled()),
                                    StringConvertor.convertorBooleanToString(user.isAccountNonExpired()),
                                    StringConvertor.convertorBooleanToString(user.isCredentialsNonExpired()),
                                    StringConvertor.convertorBooleanToString(user.isAccountNonLocked())};
        
        getJdbcTemplate().update(sql, obj);
        
        return user;
	}

	@Override
	public User find(User user) throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.find");
        
        return (User) getJdbcTemplate().queryForObject(sql, new Object[] { user.getPid(), user.getUserId() }, getRowMapper());
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<User> findList() throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.findList");
        
        return (List<User>) getJdbcTemplate().query(sql, getRowMapper());
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public List<User> findList(User user) throws DataAccessException {
	    String sql = getMessageSourceAccessor().getMessage("user.findFriendsList");
	    
	    return (List<User>) getJdbcTemplate().query(sql, new Object[] { user.getSid() }, getRowMapper());
	}

	@Override
	public int count() throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.count");
        
		return getJdbcTemplate().queryForInt(sql);
	}

	@Override
	public User modify(User user) throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.modify");
        
        Object[] obj = new Object[] { user.getPasswd(),
    								user.getEmail(),
    								user.getUserName(),
    								user.getNickName(),
    								user.getImgFile(),
    								user.getIconFile(),
    								user.getSid()};
  
        getJdbcTemplate().update(sql, obj);
      
		return user;
	}

   @Override
	public User remove(User user) throws DataAccessException {
        String sql = getMessageSourceAccessor().getMessage("user.remove");
        
        getJdbcTemplate().update(sql, new Object[] { user.getSid() });
        
        return user;
	}
   
   @SuppressWarnings("unchecked")
   @Override
   public User authenticate(User user) throws DataAccessException {
       String sql = getMessageSourceAccessor().getMessage("user.authenticate");
       
       List<User> list = (List<User>) getJdbcTemplate().query(sql, new Object[] { user.getPid(), user.getUserId() }, getAuthenticateRowMapper());
       
       User authenrityUser = null;
       UserAttribute userAttributes = new UserAttribute();

       
       for(User tempoprayUser : list) {
           authenrityUser = tempoprayUser;
           
           UserGrantedAuthority authority = new UserGrantedAuthority(tempoprayUser.getAuthority());
           
           if (ArrayUtils.contains(userAttributes.getAuthorities(), authority)) {
               int index = ArrayUtils.indexOf(userAttributes.getAuthorities(), authority);
               authority = (UserGrantedAuthority) userAttributes.getAuthorities()[index];
           } else {
               userAttributes.addAuthority(authority);
           }
           
           authenrityUser.setAuthorities(userAttributes.getAuthorities());
       }
       
       return authenrityUser;
   }   

    private RowMapper getRowMapper() {
        RowMapper rowMapper = new RowMapper() {
            public Object mapRow(ResultSet rs, int rownum) throws SQLException {
                return makeUser(rs, false);
            }
        };
        
        return rowMapper;
    }
    
    private RowMapper getAuthenticateRowMapper() {
        RowMapper rowMapper = new RowMapper() {
            public Object mapRow(ResultSet rs, int rownum) throws SQLException {
                return makeUser(rs, true);
            }
        };
        
        return rowMapper;
    }
    
    private User makeUser(ResultSet rs, boolean mode) throws SQLException {
        User user = new User();
        user.setSid(rs.getString("SID"));
        user.setPid(rs.getString("PID"));
        user.setPasswd(rs.getString("PASSWD"));
        user.setUserId(rs.getString("USER_ID"));
        user.setPasswd(rs.getString("PASSWD"));
        user.setEmail(rs.getString("EMAIL"));
        user.setUserName(rs.getString("USER_NAME"));
        user.setNickName(rs.getString("NICK_NAME"));
        user.setImgFile(rs.getString("IMG_FILE"));
        user.setIconFile(rs.getString("ICON_FILE"));
        user.setEnabled(StringConvertor.convertorStringToBoolean(rs.getString("ENABLED")));
        user.setAccountNonExpired(StringConvertor.convertorStringToBoolean(rs.getString("EXPIRED")));
        user.setCredentialsNonExpired(StringConvertor.convertorStringToBoolean(rs.getString("CREDENTIAL")));
        user.setAccountNonLocked(StringConvertor.convertorStringToBoolean(rs.getString("LOCKED")));
//        user.setUseYn(rs.getString("USE_YN"));
        
        if(mode) {
            user.setAuthority(rs.getString("AUTHORITY"));
        }
        
        return user;
    }
}
